# @Version : 1.0
# @Author  : wxz
# @File    : user_service.py
# @Time    : 2025/6/1 21:12
# @Describe: 描述...
from fastapi import Depends
from sqlmodel import Session

from apps.user.dao.user_dao import UserDAO
from apps.user.dao.user_ext_info_dao import UserExtInfoDAO
from apps.user.data_model.user_ext_info_model import UserExtInfo
from apps.user.data_model.user_model import User
from apps.user.exception.user_exception import UserAlreadyExistsException, UserNotFoundException, \
    UsernameOrPwdException, PwdInconsistent, RepeatLogin
from apps.user.schemas.user_cache import UserCache
from apps.user.schemas.user_schema import UserRegister, UserLogin
from apps.user.schemas.user_vo import UserVo
from commons.common_exception import SystemException
from config import app_settings
from config.app_logger import logger
from database.mysql.mysql_client import MySQLClient
from database.redis.redis_client import RedisClient, get_redis_client
from utils.encrypt_hash import Encrypt
from utils.id_util import IdUtil
from utils.jwt import JWT


class UserService:

    def __init__(self,
                 user_dao: UserDAO = Depends(),
                 user_ext_info_dao: UserExtInfoDAO = Depends(),
                 redis_client: RedisClient = Depends(get_redis_client),
                 db_session: Session = Depends(MySQLClient.get_db_session),
                 ):
        self.user_dao = user_dao
        self.user_ext_info_dao = user_ext_info_dao
        self.redis_client = redis_client
        self.db_session = db_session

    def find_by_user_id(self, user_id)-> UserVo:
        """
        根据用户ID查询
        """
        user = self.user_dao.find_by_id(user_id)
        # 用户不存在
        if user is None:
            raise UserNotFoundException
        # 字典解包
        user_vo = UserVo(**user.__dict__)
        return user_vo

    def find_by_username(self, username: str)-> UserVo:
        """
        根据用户名查询用户信息
        :param username:
        :return:
        """
        user = self.user_dao.find_user_by_username(username)
        # 用户不存在
        if user is None:
            raise UserNotFoundException
        # 字典解包
        user_vo = UserVo(**user.__dict__)
        return user_vo

    def register(self, user_register: UserRegister)-> True:

        # 确认密码是否一致
        if user_register.password != user_register.re_pwd:
            raise PwdInconsistent

        user = self.user_dao.find_user_by_username(user_register.username)
        # 如果用户已被注册
        if user:
            raise UserAlreadyExistsException

        try:
            # 密码加密
            pwd = Encrypt.get_password_hash(user_register.password)

            # 保存用户
            user = User()
            user.id = IdUtil.get_uuid()
            user.username = user_register.username
            user.password = pwd

            # 保存用户额外信息
            user_ext_info = UserExtInfo()
            user_ext_info.id = IdUtil.get_uuid()
            user_ext_info.user_id = user.id

            self.user_dao.save_user(user)
            self.user_ext_info_dao.save(user_ext_info)
            self.db_session.commit()

        except Exception as e:
            logger.error(e, exc_info=True)
            self.db_session.rollback()
            raise SystemException
        return True

    def login(self, user_login: UserLogin)-> str:
        """
        用户登录
        """

        user = self.user_dao.find_user_by_username(user_login.username)
        # 用户不存在
        if user is None:
            raise UserNotFoundException

        # 从redis中获取用户信息,判断用户是否已经登录
        cache_user = self.redis_client.get(user.id)
        if cache_user:
            raise RepeatLogin

        # 密码校验
        res = Encrypt.verify_password_hash(user_login.password, user.password)
        if res is False:
            raise UsernameOrPwdException

        # 获取 access_token
        access_token = JWT.create_access_token(user.id)

        # 保存到redis
        user_cache = UserCache(
            id = user.id,
            username = user.username,
            access_token=access_token
        )
        ex = app_settings.jwt.ACCESS_TOKEN_EXPIRE_MINUTES * 60
        self.redis_client.set_ex(user_cache.id, user_cache.model_dump_json(), ex)

        return access_token














